var n = { 0: "NONE", 1: "PAN", 2: "ZOOM", 4: "ROTATE", NONE: 0, PAN: 1, ROTATE: 4, ZOOM: 2 }
import Module from "./Module"
import * as THREE from "three"
import CameraControlsBase from "../controls/CameraControlsBase"
import a from "../packages/57812"
import CameraModule from "./CameraModule"
import ViewmodeData from "../data/ViewmodeData"
import { BeginSwitchViewmodeMessage, EndSwitchViewmodeMessage } from "../message/viewmode.message"
import { ScrollEvent } from "../event/ScrollEvent"
import { DragBeginEvent, DragEndEvent, DragEvent } from "../event/DragEvent"
import { KeyEvent } from "../event/KeyEvent"
import CommonControlsModule from "./CommonControlsModule"
import MeshData from "../data/MeshData"
import T from "../math/19674"
import SymbolList from "../SymbolList"
import { PinchEndEvent, PinchEvent } from "../event/GestureEvent"
import hotKeyEnum, { KeyState } from "../enum/hotKey.enum"
import viewmodeEnum from "../enum/viewmode.enum"

export default class OrthographicControlsModule extends Module {
  controlState: number
  controlsEngaged: boolean
  movementKeys: THREE.Vector2
  resetControlState: () => void
  meshData: MeshData
  cameraModule: CameraModule
  viewmodeData: ViewmodeData
  modelSize: number
  commonControlsModule: CommonControlsModule
  controls: CameraControlsBase
  constructor() {
    super(...arguments)
    this.name = "orthographic-controls"
    this.controlState = n.NONE
    this.controlsEngaged = !1
    this.movementKeys = new THREE.Vector2()
    this.resetControlState = () => {
      this.controlState = n.NONE
    }
  }
  async init(e, t) {
    const [i, n, s, r] = await Promise.all([
      t.market.waitForData(MeshData),
      t.getModule(CameraModule),
      t.getModule(CommonControlsModule),
      t.market.waitForData(ViewmodeData)
    ])
    this.meshData = i
    this.cameraModule = n
    this.viewmodeData = r
    this.modelSize = Math.max(i.size.length(), 1)
    this.commonControlsModule = s
    this.createCameraControls(i)
    t.getModuleBySymbol(SymbolList.INPUT).then(e => {
      this.bindings.push(
        e.registerHandler(ScrollEvent, e => {
          this.validateViewmode() && this.onScrollWheel(e)
        })
      )
      this.bindings.push(
        e.registerHandler(DragBeginEvent, e => {
          this.validateViewmode() && this.onDragBegin(e.buttons)
        })
      )
      this.bindings.push(
        e.registerHandler(DragEvent, e => {
          this.validateViewmode() && ((this.controlsEngaged = !0), this.onDrag(e.delta), this.controls.update(a.SI), this.controls.stop())
        })
      )
      this.bindings.push(
        e.registerHandler(DragEndEvent, e => {
          this.validateViewmode() &&
            this.controlsEngaged &&
            (e.timeSinceLastMove < 100 && (this.onDrag(e.delta), this.controls.update(a.SI), this.controls.stopAcceleration()),
            this.onDragEnd(e.delta, e.buttons),
            (this.controlsEngaged = !1))
        })
      )
      this.bindings.push(
        e.registerHandler(PinchEvent, e => {
          this.validateViewmode() && (this.controls.setZoomAcceleration(-e.pinchDelta * a.N4), this.controls.update(a.SI), this.controls.stop())
        })
      )
      this.bindings.push(e.registerHandler(PinchEndEvent, this.resetControlState))
      this.bindings.push(
        e.registerHandler(KeyEvent, e => {
          this.validateViewmode() && e.state !== KeyState.PRESSED && this.onKey(e)
        })
      )
    })
    this.bindings.push(
      t.subscribe(BeginSwitchViewmodeMessage, e => {
        this.controls.stop(), this.resetControlState()
      })
    )
    this.bindings.push(
      t.subscribe(EndSwitchViewmodeMessage, e => {
        this.validateViewmode() && this.controls.start()
      })
    )
  }
  onUpdate(e) {
    this.validateViewmode() && this.controls.update(e)
  }
  createCameraControls(e: MeshData) {
    this.controls = new CameraControlsBase(this.cameraModule, e.bounds, e.center, !0)
    this.commonControlsModule.addControls(viewmodeEnum.Orthographic, this.controls)
  }
  onScrollWheel(e) {
    if (0 !== e.delta.y) {
      const t = T.et(this.modelSize, 1, 1500, 2, 0.125)
      this.controls.setZoomAcceleration((e.delta.y * a.jX) / (t * a.mP)), this.controls.update(a.SI), this.controls.setZoomAcceleration(0)
    }
  }
  onDragBegin(e) {
    if (this.controlState === n.NONE) {
      const t = e
      this.controlState = t
    }
    this.controls.stop()
  }
  onDrag(e) {
    switch (this.controlState) {
      case n.PAN:
        const t = e
        this.controls.setPanAcceleration({ x: -t.x, y: -t.y })
        break
      case n.ZOOM:
        0 !== e.y && this.controls.setZoomAcceleration(-e.y)
    }
  }
  onDragEnd(e, t) {
    t & this.controlState || (this.controlState = n.NONE)
  }
  onKey(e) {
    const { key: t, state: i } = e,
      n = i === KeyState.DOWN
    let s = !1
    switch (t) {
      case hotKeyEnum.A:
        ;(this.movementKeys.x = n ? -1 : 0), (s = !0)
        break
      case hotKeyEnum.D:
        ;(this.movementKeys.x = n ? 1 : 0), (s = !0)
        break
      case hotKeyEnum.W:
        ;(this.movementKeys.y = n ? 1 : 0), (s = !0)
        break
      case hotKeyEnum.S:
        ;(this.movementKeys.y = n ? -1 : 0), (s = !0)
        break
      case hotKeyEnum.K:
        this.controls.setZoomAcceleration(n ? a.Gu : 0)
        break
      case hotKeyEnum.I:
        this.controls.setZoomAcceleration(n ? -a.Gu : 0)
    }
    if (s) {
      const e = this.movementKeys
      this.controls.setPanAcceleration({ x: e.x, y: e.y }, !1, a.bC)
    }
  }
  validateViewmode() {
    return this.viewmodeData.currentMode === viewmodeEnum.Orthographic
  }
}
